package com.clearmine.minesweeper.service.impl;

import com.clearmine.minesweeper.model.Cell;
import com.clearmine.minesweeper.model.GameState;
import com.clearmine.minesweeper.model.GameMessage;
import com.clearmine.minesweeper.service.GameService;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class GameServiceImpl implements GameService {
    private final Map<String, GameState> rooms = new ConcurrentHashMap<>();
    private final Map<String, String> playerRooms = new ConcurrentHashMap<>();
    private final Random random = new Random();

    public GameMessage createRoom(String playerId) {
        String roomId = generateRoomId();
        GameState gameState = createNewGameState();
        rooms.put(roomId, gameState);
        playerRooms.put(playerId, roomId);

        GameMessage response = new GameMessage();
        response.setType("ROOM_CREATED");
        response.setRoomId(roomId);
        response.setPlayerId(playerId);
        return response;
    }

    public GameMessage joinRoom(String roomId, String playerId) {
        if (!rooms.containsKey(roomId)) {
            throw new RuntimeException("房间不存在");
        }

        GameState gameState = rooms.get(roomId);
        playerRooms.put(playerId, roomId);

        GameMessage response = new GameMessage();
        response.setType("PLAYER_JOINED");
        response.setRoomId(roomId);
        response.setPlayerId(playerId);
        return response;
    }

    public GameMessage handleGameAction(GameMessage message) {
        String roomId = message.getRoomId();
        GameState gameState = rooms.get(roomId);

        if (gameState == null) {
            throw new RuntimeException("房间不存在");
        }

        // 创建游戏状态的副本，根据玩家身份过滤地雷信息
        GameState filteredState = createFilteredGameState(gameState, message.getPlayerId());

        switch (message.getAction()) {
            case "PLACE_MINE":
                handlePlaceMine(gameState, message);
                break;
            case "REVEAL_CELL":
                handleRevealCell(gameState, message);
                break;
            case "GAME_OVER":
                handleGameOver(gameState, message);
                break;
        }

        // 更新过滤后的状态
        updateFilteredState(filteredState, gameState, message.getPlayerId());

        GameMessage response = new GameMessage();
        response.setType("GAME_UPDATE");
        response.setGameState(filteredState);
        response.setRoomId(roomId);
        return response;
    }

    private GameState createFilteredGameState(GameState originalState, String playerId) {
        GameState filteredState = new GameState();
        List<List<Cell>> filteredBoard = new ArrayList<>();

        // 复制原始棋盘
        for (List<Cell> row : originalState.getBoard()) {
            List<Cell> filteredRow = new ArrayList<>();
            for (Cell cell : row) {
                Cell filteredCell = new Cell();
                // 只显示当前玩家的地雷
                boolean isCurrentPlayer = "player1".equals(playerId);
                if (cell.getIsMine()) {
                    // 如果是当前玩家的地雷，显示为已点击状态
                    if (cell.getIsPlayer1() == isCurrentPlayer) {
                        filteredCell.setIsMine(true);
                        filteredCell.setIsPlayer1(isCurrentPlayer);
                        filteredCell.setIsRevealed(false);
                    }
                    // 如果是其他玩家的地雷，显示为未点击状态（灰色格子）
                    else {
                        filteredCell.setIsMine(true);
                        filteredCell.setIsPlayer1(!isCurrentPlayer);
                        filteredCell.setIsRevealed(false);
                    }
                } else {
                    // 非地雷格子保持原样
                    filteredCell.setIsRevealed(cell.getIsRevealed());
                    filteredCell.setAdjacentMines(cell.getAdjacentMines());
                    filteredCell.setRevealedBy(new ArrayList<>(cell.getRevealedBy()));
                }
                filteredRow.add(filteredCell);
            }
            filteredBoard.add(filteredRow);
        }

        filteredState.setBoard(filteredBoard);
        filteredState.setCurrentPlayer(originalState.getCurrentPlayer());
        filteredState.setGamePhase(originalState.getGamePhase());
        filteredState.setPlayer1Alive(originalState.isPlayer1Alive());
        filteredState.setPlayer2Alive(originalState.isPlayer2Alive());
        filteredState.setGameOver(originalState.isGameOver());
        filteredState.setWinner(originalState.getWinner());

        return filteredState;
    }

    private void updateFilteredState(GameState filteredState, GameState originalState, String playerId) {
        // 更新游戏状态
        filteredState.setCurrentPlayer(originalState.getCurrentPlayer());
        filteredState.setGamePhase(originalState.getGamePhase());
        filteredState.setPlayer1Alive(originalState.isPlayer1Alive());
        filteredState.setPlayer2Alive(originalState.isPlayer2Alive());
        filteredState.setGameOver(originalState.isGameOver());
        filteredState.setWinner(originalState.getWinner());

        // 更新棋盘状态
        boolean isCurrentPlayer = "player1".equals(playerId);
        for (int i = 0; i < originalState.getBoard().size(); i++) {
            for (int j = 0; j < originalState.getBoard().get(i).size(); j++) {
                Cell originalCell = originalState.getBoard().get(i).get(j);
                Cell filteredCell = filteredState.getBoard().get(i).get(j);

                // 更新已揭示的格子
                filteredCell.setIsRevealed(originalCell.getIsRevealed());
                filteredCell.setAdjacentMines(originalCell.getAdjacentMines());
                filteredCell.setRevealedBy(new ArrayList<>(originalCell.getRevealedBy()));

                // 只显示当前玩家的地雷
                if (originalCell.getIsMine() && originalCell.getIsPlayer1() == isCurrentPlayer) {
                    filteredCell.setIsMine(true);
                    filteredCell.setIsPlayer1(isCurrentPlayer);
                    filteredCell.setIsRevealed(true);
                }
            }
        }
    }

    private void handlePlaceMine(GameState gameState, GameMessage message) {
        int row = message.getRow();
        int col = message.getCol();
        Cell cell = gameState.getBoard().get(row).get(col);

        if (cell.getIsMine()) {
            return;
        }


        cell.setIsMine(true);
        cell.setIsPlayer1(message.getPlayerId().equals("player1"));
        cell.setIsRevealed(false); // 放置地雷时立即显示

        // 检查是否所有玩家都放置了地雷
        long totalMines = gameState.getBoard().stream()
                .flatMap(List::stream)
                .filter(Cell::getIsMine)
                .count();

        if (totalMines == 2) { // 每个玩家一个地雷
            gameState.setGamePhase("playing");
            gameState.setCurrentPlayer(1);
        } else {
            gameState.setCurrentPlayer(gameState.getCurrentPlayer() == 1 ? 2 : 1);
        }
    }

    private void handleRevealCell(GameState gameState, GameMessage message) {
        int row = message.getRow();
        int col = message.getCol();
        Cell cell = gameState.getBoard().get(row).get(col);

        if (cell.getIsRevealed()) {
            return;
        }

        // 检查是否是对方的地雷
        boolean isCurrentPlayer = "player1".equals(message.getPlayerId());
        if (cell.getIsMine() && cell.getIsPlayer1() != isCurrentPlayer) {
            // 踩到对方的地雷，游戏结束
            cell.setIsRevealed(true);
            cell.getRevealedBy().add(gameState.getCurrentPlayer());

            // 设置游戏结束状态
            gameState.setGamePhase("gameOver");
            gameState.setGameOver(true);

            // 确定获胜者（踩雷的玩家失败）
            String winner = isCurrentPlayer ? "player2" : "player1";
            gameState.setWinner(winner);

            // 更新玩家状态
            if (isCurrentPlayer) {
                gameState.setPlayer1Alive(false);
            } else {
                gameState.setPlayer2Alive(false);
            }

        } else {
            // 正常揭示格子
            cell.setIsRevealed(true);
            cell.getRevealedBy().add(gameState.getCurrentPlayer());
            gameState.setCurrentPlayer(gameState.getCurrentPlayer() == 1 ? 2 : 1);
        }
    }

    private void handleGameOver(GameState gameState, GameMessage message) {
        gameState.setGamePhase("gameOver");
        gameState.setGameOver(true);
        gameState.setWinner(message.getWinner());

        // 更新玩家状态
        if ("player1".equals(message.getWinner())) {
            gameState.setPlayer2Alive(false);
        } else {
            gameState.setPlayer1Alive(false);
        }
    }

    private GameState createNewGameState() {
        GameState gameState = new GameState();
        List<List<Cell>> board = new ArrayList<>();

        for (int i = 0; i < 5; i++) {
            List<Cell> row = new ArrayList<>();
            for (int j = 0; j < 5; j++) {
                Cell cell = new Cell();
                cell.setIsMine(false);
                cell.setIsRevealed(false);
                cell.setIsPlayer1(false);
                cell.setAdjacentMines(0);
                cell.setRevealedBy(new ArrayList<>());
                row.add(cell);
            }
            board.add(row);
        }

        gameState.setBoard(board);
        gameState.setCurrentPlayer(1);
        gameState.setGamePhase("placing");
        gameState.setPlayer1Alive(true);
        gameState.setPlayer2Alive(true);
        gameState.setGameOver(false);
        gameState.setWinner(null);

        return gameState;
    }

    private String generateRoomId() {
        return String.format("%04d", random.nextInt(10000));
    }

}